// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UriExtensions.cs" company="AzureContrib (Open source library http://azurecontrib.codeplex.com)">
//   Microsoft Public License (Ms-PL)
// </copyright>
// <summary>
//   Extension methods to Uri
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Diagnostics.CodeAnalysis;
using System.Web;

namespace AzureContrib.WindowsAzure
{
	/// <summary>
	/// Extension methods to Uri
	/// </summary>
	public static class UriExtensions
	{
		/// <summary>
		/// A slash '/' character.
		/// </summary>
		public const char Slash = '/';

		/// <summary>
		/// Convert a <see cref="Uri"/> to a uniqe url safe string
		/// </summary>
		/// <param name="uri">The <see cref="Uri"/> to convert</param>
		/// <returns>An url safe string</returns>
		[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "AzureContrib.WindowsAzure.Core.Assumes.NotNull handles null checking.")]
		public static string ExtractUniqueUrlSafeKeyFromUri(this Uri uri)
		{
			Assumes.NotNull(uri, "uri");

			var encodedUrl = HttpUtility.UrlEncode(uri.AbsoluteUri);

			return encodedUrl != null ?
						 encodedUrl.Replace('%', 'A') :
						 string.Empty;
		}

		/// <summary>
		/// Append a relative path to an existing base uri and return a new Uri instance with the combined path.
		/// </summary>
		/// <param name="baseUri">
		/// The base Uri.
		/// </param>
		/// <param name="relativePathToAppend">
		/// The relative Uri Path To Append.
		/// </param>
		/// <returns>
		/// A new instance of a Uri appended with the relative path.
		/// </returns>
		public static Uri Append(this Uri baseUri, string relativePathToAppend)
		{
			if (string.IsNullOrEmpty(relativePathToAppend))
			{
				return baseUri;
			}

			var uriBuilder = new UriBuilder(baseUri);
			var currentPath = uriBuilder.Path.TrimEnd(Slash);
			relativePathToAppend = relativePathToAppend.TrimStart(Slash);
			uriBuilder.Path = string.Concat(
				currentPath,
				Slash /* This will avoid the dreaded doubleslash. */, 
				relativePathToAppend);
			return uriBuilder.Uri;
		}

		/// <summary>
		/// Gets the file name portion of a <see cref="Uri"/> minus query strings and all other uri information.
		/// </summary>
		/// <param name="uri">The <see cref="Uri"/> to get the file name from.</param>
		/// <param name="parentFolderUri">The <see cref="Uri"/> for the parent folder.</param>
		/// <returns>The file name.</returns>
		[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "AzureContrib.WindowsAzure.Core.Assumes.NotNull handles null checking.")]
		[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1", Justification = "AzureContrib.WindowsAzure.Core.Assumes.NotNull handles null checking.")]
		public static string GetFileName(this Uri uri, Uri parentFolderUri)
		{
			Assumes.NotNull(uri, "uri");
			Assumes.NotNull(parentFolderUri, "parentFolderUri");
			return uri.AbsolutePath.Replace(parentFolderUri.AbsolutePath, string.Empty).Trim(Slash);
		}
	}
}